#ifndef CALIBRATION_H
#define CALIBRATION_H

#include "MotionManager/motionmanager.h"
#include "VisionLocation/visionlocation.h"
#include "calibrationconfig.h"
#include "pixel2mech.h"
#include "scvision_global.h"
#include <QObject>
#include <QPointF>
#include <QVector>
#include <qmath.h>

typedef std::function<void(double, double, QVector<QPointF> &, QVector<QPointF> &)> CustomCaliFunc;
typedef std::function<void(PrOffset)> CustomPerformPrResultFunc;

class SCVISIONSHARED_EXPORT Calibration : public QObject
{
    Q_OBJECT

public:
    explicit Calibration(CalibrationConfig *config, VisionLocation *location, QObject *parent = nullptr);

    QString calibrationName() const;

    void performCalibration();

    void performPRResult(PrOffset offset);

    void performPROriginResult(PrOffset offset);

    double getRotationAngle();

    bool getDeltaDistanceFromCenter(const QPointF pixelPoint, QPointF &distanceMech);

    QPointF getOnePxielDistance();

    QPointF getOneXPxielDistance();

    QPointF getOneYPxielDistance();

    double caculateRotationAngle();

    bool getMechPoint(QPointF pixelPoint, QPointF &mechPoint);

    bool getCaliMapping(Pixel2Mech &caliMapping);

    Pixel2Mech *getCaliMapping();

    void setCustomFunc(CustomCaliFunc customCaliFunc, CustomPerformPrResultFunc customPerformPrResultFunc);

    virtual void GetPixelPoint(double &x, double &y);

private:
    void getCorrespondingPixelMotorPoints(double xMove,
                                          double yMove,
                                          QVector<QPointF> &pixelPoints,
                                          QVector<QPointF> &motorPoints);

    void coordinateA2BMapping(const QVector<QPointF> &APoints, const QVector<QPointF> &BPoints);

    bool calculateMatrixAttribute(
        QVector<QPointF> p, QVector<QPointF> m, double &scaleX, double &scaleY, double &closestAngle);

private:
    CalibrationConfig *config;
    VisionLocation *location;

    Pixel2Mech mapping;
    Pixel2Mech mA2BMapping;
    bool mIsMapping;
    QMatrix mA2BMatrix;
    QPointF mOriginB;
    double mRotationB;

    CustomCaliFunc customCaliFunc = nullptr;
    CustomPerformPrResultFunc customPerformPrResultFunc = nullptr;
};

#endif    // CALIBRATION_H
